package main

import (
	"fmt"
	"retriever/mock"
	"retriever/real"
	"time"
)

const url = "https://www.imooc.com"

type Retriever interface {
	Get(url string) string

	/*
		todo: 接口变量里有什么
		- 接口变量自带指针
		- 接口变量同样采用值传递, 几乎不需要使用接口指针
		- 指针接收者实现只能以指针方式使用;值接收都可(编译器不是总能找到值的地址)
		todo: 查看接口变量
		- 表示任何类型: interface{}  # type Q []int   ==> type []interface{}
		- Type Assertion
		- Type Switch
	*/
}

type Poster interface {
	Post(url string, form map[string]string) string
}

func download(r Retriever) string {
	return r.Get(url)
}

func post(poster Poster) {
	poster.Post(url,
		map[string]string{
			"name":   "ccmouse",
			"course": "golang",
		})
}

type RetrieverPoster interface {
	Retriever
	Poster
}

func session(s RetrieverPoster) string {
	s.Post(url, map[string]string{
		"contents": "another faked imooc.com",
	})
	return s.Get(url)
}

func inspect(r Retriever) {
	fmt.Println("Inspecting", r)
	fmt.Printf(" > %T %v\n", r, r) //%T (type打印类型) %v 打印值
	fmt.Print(" > Type Switch:")
	switch v := r.(type) {
	case *mock.Retriever:
		fmt.Println("Contents:", v.Contents)
	case real.Retriever:
		fmt.Println("UserAgent: ", v.UserAgent)
	}
}

func main() {
	var r Retriever
	retriever := mock.Retriever{"this is a fake imooc.com"}
	r = &retriever
	inspect(r)
	r = real.Retriever{
		UserAgent: "Mozilla/5.0",
		TimeOut:   time.Minute,
	}
	fmt.Println()
	inspect(r)
	// Type assertion
	if realRetriever, ok := r.(real.Retriever); ok {
		fmt.Println(realRetriever.TimeOut)
	} else {
		fmt.Println("not a mock retriever")
	}

	fmt.Println("Try a session")
	fmt.Println(session(&retriever))

	//fmt.Println(download(r))
}
